// normal and vertex in the camera frame
varying vec3 N;
varying vec3 v;

// coordinate in the shadowmap
varying vec4 ShadowCoord;

// Blin-Phong
uniform vec4 Ambient;
uniform vec4 Diffuse;
uniform vec4 Specular;
uniform float Shininess;
uniform vec4 Emission;

// Shadowmap
uniform sampler2D smTex;

// scale the depth
uniform float depthScale;

// 0: in shadow. 1: not.
float Visibility() {

	// exceed the frustrum -----------------------------
//	if( ShadowCoord.w == 0.f ) return 0.5f;	

	//
	vec3 shadowCoordinateWdivide = ShadowCoord.xyz / ShadowCoord.w;
		
	//* // scale x y z to [0 1]
	shadowCoordinateWdivide.x = shadowCoordinateWdivide.x * 0.5f + 0.5f;
	shadowCoordinateWdivide.y = shadowCoordinateWdivide.y * 0.5f + 0.5f;
	shadowCoordinateWdivide.z = shadowCoordinateWdivide.z * 0.5f + 0.5f; // */

	// exceed the texture -----------------------------
	if( shadowCoordinateWdivide.x < 0 || shadowCoordinateWdivide.x > 1 ) return 0.5f;
	if( shadowCoordinateWdivide.y < 0 || shadowCoordinateWdivide.y > 1 ) return 0.5f;
	if( shadowCoordinateWdivide.z < 0 || shadowCoordinateWdivide.z > 1 ) return 0.5f;	

	// distance to light -----------------------------
	float dist = shadowCoordinateWdivide.z;

	// depth in the texture -----------------------------
	float depth = texture2D(smTex, shadowCoordinateWdivide.xy).z;

	// compare depths -----------------------------
	if( depth < dist - 0.01f ) return 0.5f;

	return 1.f;
}

// Blinn-Phong shading
vec4 BlinnPhong(vec4 ambient, vec4 diffuse, vec4 specular, float shininess, vec4 emission, vec4 gamb, vec4 iamb) {

	// we are in Eye Coordinates (camera frame), so EyePos is (0,0,0)
	vec3 L = normalize(gl_LightSource[0].position.xyz - v);
	vec3 E = normalize(-v);
	float NdotL = max(dot(N, L), 0.0);
	
	// calculate Diffuse Term:
	vec4 Idiff = NdotL * diffuse * gl_LightSource[0].diffuse;

	// calculate Specular Term:
	vec4 Ispec = vec4(0.0, 0.0, 0.0, 0.0);
	if (NdotL > 0.0) {
		float NdotHV = max( dot(N, normalize(E+L)), 0.0 );
		Ispec = specular * gl_LightSource[0].specular * pow(NdotHV, shininess);
	}

	// Total Color:
	return (gamb + iamb + Idiff + Ispec + emission);
}

void main (void) {
	
	vec4 ambient = Ambient;
	vec4 diffuse = Diffuse;
	vec4 specular = Specular;
	float shininess = Shininess;
	vec4 emission = Emission;

	// global ambient
	vec4 gamb = ambient * gl_LightModel.ambient;
	// light ambient
	vec4 iamb = ambient * gl_LightSource[0].ambient;

	vec4 shade = BlinnPhong(ambient, diffuse, specular, shininess, emission, gamb, iamb);
	float vis = Visibility();

	gl_FragColor =	gl_FrontLightModelProduct.sceneColor + vis * shade;
}